﻿using System;

namespace DailyFx.UI
{
    public sealed class WeakAction
    {
		/// <summary>
		///		the target object .
		/// </summary>
        private readonly WeakReference _target;
        
		/// <summary>
        ///		type info of the concrete method .
        /// </summary>
		private readonly Type _ownerType;
        
		/// <summary>
		///		type info of action delegate .
		/// </summary>
		private readonly Type _actionType;
        
		/// <summary>
		///		the name of the concrete method .
		/// </summary>
		private readonly String _methodName;
        
		/// <summary>
		///		the task mode to run concrete method .
		/// </summary>
		private readonly TaskKind _taskKind;



		/// <summary>
		///		c'tor
		/// </summary>
        public WeakAction ( Delegate handler, Type actionType, TaskKind taskKind )
        {
            if (handler.Method.IsStatic)
                this._ownerType = handler.Method.DeclaringType;
            else
                this._target = new WeakReference ( handler.Target );

            this._methodName = handler.Method.Name;
            this._actionType = actionType;
            this._taskKind= taskKind;
        }

		/// <summary>
		///		Gets the target object .
		/// </summary>
        public WeakReference Target
        {
            get { return this._target; }
        }

		/// <summary>
		///		Gets the type of action delegate .
		/// </summary>
		public Type ActionType
		{
			get { return _actionType; }
		}

		/// <summary>
		///		Gets the task mode .
		/// </summary>
        public TaskKind TaskMode
        {
            get { return this._taskKind; }
        }

      
		/// <summary>
		///		Checks if this is recycled to cache buffer .
		/// </summary>
        public bool HasBeenCollected
        {
            get
            {
                return (_ownerType == null && (_target == null || !_target.IsAlive));
            }
        }

		/// <summary>
		///		Returns the actual delegate to run .
		/// </summary>
        public Delegate GetMethod ()
        {
            if ( this._ownerType != null )
            {
                return Delegate.CreateDelegate( this._actionType, this._ownerType, this._methodName );
            }

            if ( this._target != null && this._target.IsAlive )
            {
                object target = this._target.Target;
                if ( target != null )
                    return Delegate.CreateDelegate( this._actionType, target, this._methodName);
            }

            return null;
        }
    }

}
